This project focuses on designing and optimizing a convolutional neural network (CNN) for the classification of political memes into conservative and liberal viewpoints, aiming to achieve the highest possible accuracy on a validation set. The process includes employing techniques like early stopping and model checkpointing to monitor performance, and making adjustments to the CNN architecture based on changes in accuracy related to hyperparameters such as filters and layers. The task emphasizes reproducibility through a pre-determined data split and involves the creation of separate data generators for training, validation, and testing. The project’s success will be ultimately evaluated on an independent test set, with learning curves and detailed analysis included in the final report.
For this project, the image dataset was sourced by exploring meme-focused pages on social platforms such as Reddit, Facebook, and Pinterest. A total of 1,000 images were collected, with an equal distribution between conservative and liberal political themes.
Special thanks to Kate Arendes for contributions to the collection process.
import PIL
import numpy as np
from PIL import Image
from keras import layers
from tensorflow import keras
from keras import regularizers
from google.colab import drive
import matplotlib.pyplot as plt
from keras.metrics import Precision
from keras.preprocessing.image import ImageDataGenerator
First, lets download the images from google drive:# Let's mount the drive to load the images
drive.mount('/content/drive')
Mounted at /content/drive
# Let's set the base directory for loading the political meme images
base_directory = "/content/drive/My Drive/Political Meme Dataset/"
# Let's initialize the ImageDataGenerator with rescaling to normalize pixel values
my_generator = ImageDataGenerator(rescale=1./255)
# Let's set up the training data generator
# This loads images of size 150x150, in batches of 4, with binary class labels
train_generator = my_generator.flow_from_directory(
f"{base_directory}/training/",
target_size=(150, 150),
batch_size=4,
class_mode='binary'
)
# Let's set up the validation data generator
# Loads images of the same size and batch size as the training generator
valid_generator = my_generator.flow_from_directory(
f"{base_directory}/validation/",
target_size=(150, 150),
batch_size=4,
class_mode='binary'
)
# Let's set up the test data generator
# Uses the same parameters for consistency across training, validation, and testing
test_generator = my_generator.flow_from_directory(
f"{base_directory}/test/",
target_size=(150, 150),
batch_size=4,
class_mode='binary'
)
Found 600 images belonging to 2 classes. Found 200 images belonging to 2 classes. Found 200 images belonging to 2 classes.
# Let's load a single image using PIL library.
image = Image.open(f"{base_directory}/training/train_liberal/0f76446d7d65a9e6508a226ae33e8a51--felder-donald-oconnor.jpg")
# Let's get some details about the image.
print("Image Mode -->", image.mode)
print("Image Format --> ", image.format)
print("Image Size -->", image.size)
Image Mode --> RGB Image Format --> JPEG Image Size --> (118, 108)
# Let's display the colored image
plt.imshow(np.asarray(image))
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x7c63946f7f40>
# Let's convert the input image to grayscale
gs_image = image.convert(mode='L')
# Let's display the grayscale image using matplotlib
plt.imshow(np.asarray(gs_image), cmap='gray')
<matplotlib.image.AxesImage at 0x7c63945eb3d0>
# Let's resize the image to 200x200 pixels
img_resized = image.resize((200,200))
# Let's print the size of the resized image to verify the new dimensions
print(img_resized.size)
# Let's display the resized image using matplotlib
plt.imshow(np.asarray(img_resized))
(200, 200)
<matplotlib.image.AxesImage at 0x7c639466fc10>
# Let's loop through batches of images from the train generator
for my_batch in train_generator:
images = my_batch[0]
labels = my_batch[1]
# Let's iterate over each image and its corresponding label in the batch
for i in range(len(labels)):
plt.imshow(images[i])
plt.colorbar()
plt.show()
# Let's print the label associated with the image
print(labels[i])
break
1.0
1.0
1.0
1.0
# Let's loop through batches of images from the validation generator
for my_batch in valid_generator:
images = my_batch[0]
labels = my_batch[1]
# Let's iterate over each image and its corresponding label in the batch
for i in range(len(labels)):
plt.imshow(images[i])
plt.colorbar()
plt.show()
# Let's print the label associated with the image
print(labels[i])
break
0.0
0.0
0.0
0.0
# Let's loop through batches of images from the test generator
for my_batch in test_generator:
images = my_batch[0]
labels = my_batch[1]
# Let's iterate over each image and its corresponding label in the batch
for i in range(len(labels)):
plt.imshow(images[i])
plt.colorbar()
plt.show()
# Let's print the label associated with the image
print(labels[i])
break
0.0
0.0
1.0
1.0
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model = keras.Model(inputs=inputs, outputs=outputs)
model.summary()
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 150, 150, 3)] 0
conv2d (Conv2D) (None, 150, 150, 32) 896
max_pooling2d (MaxPooling2 (None, 75, 75, 32) 0
D)
conv2d_1 (Conv2D) (None, 75, 75, 64) 18496
max_pooling2d_1 (MaxPoolin (None, 37, 37, 64) 0
g2D)
conv2d_2 (Conv2D) (None, 37, 37, 128) 73856
max_pooling2d_2 (MaxPoolin (None, 18, 18, 128) 0
g2D)
conv2d_3 (Conv2D) (None, 18, 18, 128) 147584
max_pooling2d_3 (MaxPoolin (None, 9, 9, 128) 0
g2D)
conv2d_4 (Conv2D) (None, 9, 9, 256) 295168
max_pooling2d_4 (MaxPoolin (None, 4, 4, 256) 0
g2D)
global_average_pooling2d ( (None, 256) 0
GlobalAveragePooling2D)
dropout (Dropout) (None, 256) 0
dense (Dense) (None, 1) 257
=================================================================
Total params: 536257 (2.05 MB)
Trainable params: 536257 (2.05 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history = model.fit(train_generator, validation_data = valid_generator, epochs = 10, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/10 150/150 [==============================] - 199s 1s/step - loss: 0.6202 - accuracy: 0.6500 - precision: 0.7320 - val_loss: 0.4253 - val_accuracy: 0.8500 - val_precision: 0.7734 Epoch 2/10 150/150 [==============================] - 5s 32ms/step - loss: 0.5194 - accuracy: 0.7867 - precision: 0.7350 - val_loss: 0.2858 - val_accuracy: 0.9350 - val_precision: 0.8991 Epoch 3/10 150/150 [==============================] - 4s 26ms/step - loss: 0.4284 - accuracy: 0.8450 - precision: 0.8090 - val_loss: 0.3491 - val_accuracy: 0.8600 - val_precision: 0.7812 Epoch 4/10 150/150 [==============================] - 4s 25ms/step - loss: 0.3633 - accuracy: 0.8717 - precision: 0.8431 - val_loss: 0.3017 - val_accuracy: 0.8750 - val_precision: 0.8000 Epoch 5/10 150/150 [==============================] - 5s 34ms/step - loss: 0.3063 - accuracy: 0.8950 - precision: 0.8762 - val_loss: 0.1791 - val_accuracy: 0.9350 - val_precision: 0.8991 Epoch 6/10 150/150 [==============================] - 5s 33ms/step - loss: 0.2899 - accuracy: 0.8933 - precision: 0.8856 - val_loss: 0.1402 - val_accuracy: 0.9550 - val_precision: 0.9333 Epoch 7/10 150/150 [==============================] - 4s 25ms/step - loss: 0.3007 - accuracy: 0.8850 - precision: 0.8714 - val_loss: 0.1609 - val_accuracy: 0.9450 - val_precision: 0.9083 Epoch 8/10 150/150 [==============================] - 4s 26ms/step - loss: 0.2741 - accuracy: 0.8933 - precision: 0.8758 - val_loss: 0.1597 - val_accuracy: 0.9400 - val_precision: 0.9490 Epoch 9/10 150/150 [==============================] - 4s 26ms/step - loss: 0.2322 - accuracy: 0.9117 - precision: 0.9049 - val_loss: 0.2915 - val_accuracy: 0.8750 - val_precision: 0.8000 Epoch 10/10 150/150 [==============================] - 5s 33ms/step - loss: 0.2330 - accuracy: 0.9150 - precision: 0.9055 - val_loss: 0.1091 - val_accuracy: 0.9650 - val_precision: 0.9346
train_accuracy = history.history["accuracy"]
train_loss = history.history["loss"]
train_precision = history.history["precision"]
val_accuracy = history.history["val_accuracy"]
val_loss = history.history["val_loss"]
val_precision = history.history["val_precision"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 70s 1s/step - loss: 0.1488 - accuracy: 0.9450 - precision: 0.9083
[0.14878995716571808, 0.9449999928474426, 0.9082568883895874]
The initial model architecture resulted in a training accuracy of 0.9150 and a validation accuracy of 0.9650 after being trained for 10 epochs. The next steps include increasing the number of epochs to 50 to observe how the training and validation accuracies change across different epochs. This extended training period will help determine if the model is benefiting from more training time or if it begins to overfit the training data. Observing the trend in validation accuracy will also indicate whether the model generalizes well to unseen data. Additional measures, such as implementing early stopping or adjusting the learning rate, may be considered based on the outcomes observed at different epochs.
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model_increase_epochs = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model_increase_epochs.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="base_model_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_increase_epochs = model_increase_epochs.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 7s 34ms/step - loss: 0.6681 - accuracy: 0.6400 - precision_1: 0.7283 - val_loss: 0.5018 - val_accuracy: 0.7050 - val_precision_1: 0.9767 Epoch 2/30 150/150 [==============================] - 5s 32ms/step - loss: 0.5604 - accuracy: 0.7417 - precision_1: 0.6986 - val_loss: 0.3345 - val_accuracy: 0.9050 - val_precision_1: 0.8462 Epoch 3/30 150/150 [==============================] - 5s 32ms/step - loss: 0.4619 - accuracy: 0.8300 - precision_1: 0.7878 - val_loss: 0.2333 - val_accuracy: 0.9350 - val_precision_1: 0.9485 Epoch 4/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3606 - accuracy: 0.8667 - precision_1: 0.8481 - val_loss: 0.1744 - val_accuracy: 0.9450 - val_precision_1: 0.9083 Epoch 5/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3189 - accuracy: 0.8867 - precision_1: 0.8648 - val_loss: 0.3221 - val_accuracy: 0.8650 - val_precision_1: 0.7874 Epoch 6/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2795 - accuracy: 0.8900 - precision_1: 0.8750 - val_loss: 0.2305 - val_accuracy: 0.9100 - val_precision_1: 0.8534 Epoch 7/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2659 - accuracy: 0.8983 - precision_1: 0.8893 - val_loss: 0.2251 - val_accuracy: 0.9100 - val_precision_1: 0.8475 Epoch 8/30 150/150 [==============================] - 5s 34ms/step - loss: 0.2727 - accuracy: 0.9000 - precision_1: 0.8774 - val_loss: 0.1218 - val_accuracy: 0.9700 - val_precision_1: 0.9434 Epoch 9/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2570 - accuracy: 0.9000 - precision_1: 0.8822 - val_loss: 0.1621 - val_accuracy: 0.9400 - val_precision_1: 0.8929 Epoch 10/30 150/150 [==============================] - 5s 32ms/step - loss: 0.2214 - accuracy: 0.9183 - precision_1: 0.9115 - val_loss: 0.1031 - val_accuracy: 0.9800 - val_precision_1: 0.9615 Epoch 11/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2301 - accuracy: 0.9267 - precision_1: 0.9051 - val_loss: 0.1854 - val_accuracy: 0.9300 - val_precision_1: 0.8772 Epoch 12/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1989 - accuracy: 0.9167 - precision_1: 0.9139 - val_loss: 0.1405 - val_accuracy: 0.9500 - val_precision_1: 0.9091 Epoch 13/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1891 - accuracy: 0.9300 - precision_1: 0.9272 - val_loss: 0.1747 - val_accuracy: 0.9450 - val_precision_1: 0.9009 Epoch 14/30 150/150 [==============================] - 5s 32ms/step - loss: 0.1630 - accuracy: 0.9433 - precision_1: 0.9375 - val_loss: 0.0907 - val_accuracy: 0.9800 - val_precision_1: 0.9615 Epoch 15/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1811 - accuracy: 0.9367 - precision_1: 0.9253 - val_loss: 0.1499 - val_accuracy: 0.9450 - val_precision_1: 0.9684 Epoch 16/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2170 - accuracy: 0.9217 - precision_1: 0.9068 - val_loss: 0.1063 - val_accuracy: 0.9800 - val_precision_1: 0.9706 Epoch 17/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1379 - accuracy: 0.9467 - precision_1: 0.9437 - val_loss: 0.1222 - val_accuracy: 0.9550 - val_precision_1: 0.9174 Epoch 18/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1645 - accuracy: 0.9500 - precision_1: 0.9470 - val_loss: 0.1143 - val_accuracy: 0.9750 - val_precision_1: 0.9524 Epoch 19/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1494 - accuracy: 0.9550 - precision_1: 0.9505 - val_loss: 0.0843 - val_accuracy: 0.9700 - val_precision_1: 0.9434 Epoch 20/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1190 - accuracy: 0.9567 - precision_1: 0.9567 - val_loss: 0.1034 - val_accuracy: 0.9650 - val_precision_1: 0.9346 Epoch 21/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1254 - accuracy: 0.9517 - precision_1: 0.9502 - val_loss: 0.0670 - val_accuracy: 0.9800 - val_precision_1: 0.9800 Epoch 22/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0907 - accuracy: 0.9700 - precision_1: 0.9669 - val_loss: 0.0982 - val_accuracy: 0.9600 - val_precision_1: 0.9259 Epoch 23/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1091 - accuracy: 0.9600 - precision_1: 0.9539 - val_loss: 0.1310 - val_accuracy: 0.9500 - val_precision_1: 0.9091 Epoch 24/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0839 - accuracy: 0.9750 - precision_1: 0.9766 - val_loss: 0.1317 - val_accuracy: 0.9500 - val_precision_1: 0.9167 Epoch 25/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1083 - accuracy: 0.9633 - precision_1: 0.9572 - val_loss: 0.1508 - val_accuracy: 0.9500 - val_precision_1: 0.9091 Epoch 26/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1124 - accuracy: 0.9650 - precision_1: 0.9635 - val_loss: 0.1365 - val_accuracy: 0.9450 - val_precision_1: 0.9009 Epoch 27/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0669 - accuracy: 0.9850 - precision_1: 0.9770 - val_loss: 0.1400 - val_accuracy: 0.9650 - val_precision_1: 0.9346 Epoch 28/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0420 - accuracy: 0.9917 - precision_1: 0.9900 - val_loss: 0.1045 - val_accuracy: 0.9700 - val_precision_1: 0.9434 Epoch 29/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0463 - accuracy: 0.9900 - precision_1: 0.9836 - val_loss: 0.0764 - val_accuracy: 0.9700 - val_precision_1: 0.9608 Epoch 30/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0541 - accuracy: 0.9833 - precision_1: 0.9770 - val_loss: 0.2213 - val_accuracy: 0.9450 - val_precision_1: 0.9238
train_accuracy = history_increase_epochs.history["accuracy"]
train_loss = history_increase_epochs.history["loss"]
train_precision = history_increase_epochs.history["precision_1"]
val_accuracy = history_increase_epochs.history["val_accuracy"]
val_loss = history_increase_epochs.history["val_loss"]
val_precision = history_increase_epochs.history["val_precision_1"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
best_model = keras.models.load_model("base_model_checkpoint_filepath")
best_model.evaluate(test_generator)
50/50 [==============================] - 1s 16ms/step - loss: 0.1348 - accuracy: 0.9650 - precision_1: 0.9429
[0.13483797013759613, 0.9649999737739563, 0.9428571462631226]
Increasing the number of epochs from 10 to 30 resulted in an increase in training accuracy from 0.93 to 0.99. Similarly, the validation accuracy increased from 0.9650 to 0.98. As expected, the time required for training increased significantly from 3 minutes to 5 minutes due to the higher number of epochs. This indicates that the model benefited from additional training, as evidenced by the improvements in both training and validation accuracies.
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model_decrease_layers = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model_decrease_layers.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="decrease_layers_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_decrease_layers = model_decrease_layers.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 7s 33ms/step - loss: 0.6517 - accuracy: 0.6250 - precision_2: 0.6728 - val_loss: 0.7375 - val_accuracy: 0.5100 - val_precision_2: 0.5051 Epoch 2/30 150/150 [==============================] - 5s 32ms/step - loss: 0.5341 - accuracy: 0.7783 - precision_2: 0.7434 - val_loss: 0.4411 - val_accuracy: 0.7950 - val_precision_2: 0.7092 Epoch 3/30 150/150 [==============================] - 5s 33ms/step - loss: 0.5041 - accuracy: 0.8083 - precision_2: 0.7577 - val_loss: 0.3115 - val_accuracy: 0.8850 - val_precision_2: 0.8130 Epoch 4/30 150/150 [==============================] - 5s 33ms/step - loss: 0.4163 - accuracy: 0.8483 - precision_2: 0.8083 - val_loss: 0.2468 - val_accuracy: 0.9200 - val_precision_2: 0.8750 Epoch 5/30 150/150 [==============================] - 5s 34ms/step - loss: 0.3555 - accuracy: 0.8583 - precision_2: 0.8308 - val_loss: 0.2346 - val_accuracy: 0.9400 - val_precision_2: 0.9151 Epoch 6/30 150/150 [==============================] - 5s 32ms/step - loss: 0.3436 - accuracy: 0.8700 - precision_2: 0.8405 - val_loss: 0.2314 - val_accuracy: 0.9300 - val_precision_2: 0.9388 Epoch 7/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3298 - accuracy: 0.8783 - precision_2: 0.8450 - val_loss: 0.2823 - val_accuracy: 0.8900 - val_precision_2: 0.8197 Epoch 8/30 150/150 [==============================] - 5s 32ms/step - loss: 0.3557 - accuracy: 0.8617 - precision_2: 0.8338 - val_loss: 0.2104 - val_accuracy: 0.9350 - val_precision_2: 0.8919 Epoch 9/30 150/150 [==============================] - 5s 32ms/step - loss: 0.3117 - accuracy: 0.8967 - precision_2: 0.8742 - val_loss: 0.1808 - val_accuracy: 0.9450 - val_precision_2: 0.9495 Epoch 10/30 150/150 [==============================] - 5s 32ms/step - loss: 0.3122 - accuracy: 0.8833 - precision_2: 0.8571 - val_loss: 0.1563 - val_accuracy: 0.9450 - val_precision_2: 0.9588 Epoch 11/30 150/150 [==============================] - 5s 32ms/step - loss: 0.2918 - accuracy: 0.9000 - precision_2: 0.8797 - val_loss: 0.1460 - val_accuracy: 0.9600 - val_precision_2: 0.9423 Epoch 12/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2558 - accuracy: 0.9167 - precision_2: 0.8882 - val_loss: 0.1609 - val_accuracy: 0.9500 - val_precision_2: 0.9091 Epoch 13/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2631 - accuracy: 0.9067 - precision_2: 0.8813 - val_loss: 0.1677 - val_accuracy: 0.9550 - val_precision_2: 0.9333 Epoch 14/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2219 - accuracy: 0.9067 - precision_2: 0.8861 - val_loss: 0.2368 - val_accuracy: 0.9050 - val_precision_2: 0.8403 Epoch 15/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2449 - accuracy: 0.9200 - precision_2: 0.8987 - val_loss: 0.1926 - val_accuracy: 0.9300 - val_precision_2: 0.8772 Epoch 16/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2258 - accuracy: 0.9200 - precision_2: 0.9038 - val_loss: 0.1580 - val_accuracy: 0.9450 - val_precision_2: 0.9009 Epoch 17/30 150/150 [==============================] - 5s 32ms/step - loss: 0.2009 - accuracy: 0.9317 - precision_2: 0.9218 - val_loss: 0.1254 - val_accuracy: 0.9450 - val_precision_2: 0.9009 Epoch 18/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2088 - accuracy: 0.9333 - precision_2: 0.9194 - val_loss: 0.1299 - val_accuracy: 0.9550 - val_precision_2: 0.9174 Epoch 19/30 150/150 [==============================] - 5s 34ms/step - loss: 0.1619 - accuracy: 0.9433 - precision_2: 0.9318 - val_loss: 0.1245 - val_accuracy: 0.9400 - val_precision_2: 0.8929 Epoch 20/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1533 - accuracy: 0.9450 - precision_2: 0.9349 - val_loss: 0.1285 - val_accuracy: 0.9450 - val_precision_2: 0.9009 Epoch 21/30 150/150 [==============================] - 5s 32ms/step - loss: 0.1458 - accuracy: 0.9450 - precision_2: 0.9320 - val_loss: 0.0757 - val_accuracy: 0.9800 - val_precision_2: 0.9706 Epoch 22/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1408 - accuracy: 0.9533 - precision_2: 0.9387 - val_loss: 0.1408 - val_accuracy: 0.9400 - val_precision_2: 0.9783 Epoch 23/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1162 - accuracy: 0.9633 - precision_2: 0.9572 - val_loss: 0.2011 - val_accuracy: 0.9400 - val_precision_2: 0.9490 Epoch 24/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1387 - accuracy: 0.9433 - precision_2: 0.9263 - val_loss: 0.1752 - val_accuracy: 0.9250 - val_precision_2: 0.8696 Epoch 25/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1061 - accuracy: 0.9633 - precision_2: 0.9542 - val_loss: 0.1848 - val_accuracy: 0.9200 - val_precision_2: 0.8621 Epoch 26/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1411 - accuracy: 0.9367 - precision_2: 0.9309 - val_loss: 0.3246 - val_accuracy: 0.8750 - val_precision_2: 0.8000 Epoch 27/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1011 - accuracy: 0.9600 - precision_2: 0.9481 - val_loss: 0.1695 - val_accuracy: 0.9300 - val_precision_2: 0.8772 Epoch 28/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0907 - accuracy: 0.9700 - precision_2: 0.9608 - val_loss: 0.0899 - val_accuracy: 0.9550 - val_precision_2: 0.9174 Epoch 29/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1106 - accuracy: 0.9633 - precision_2: 0.9542 - val_loss: 0.1722 - val_accuracy: 0.9150 - val_precision_2: 0.8547 Epoch 30/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0912 - accuracy: 0.9650 - precision_2: 0.9574 - val_loss: 0.0961 - val_accuracy: 0.9650 - val_precision_2: 0.9515
train_accuracy = history_decrease_layers.history["accuracy"]
train_loss = history_decrease_layers.history["loss"]
train_precision = history_decrease_layers.history["precision_2"]
val_accuracy = history_decrease_layers.history["val_accuracy"]
val_loss = history_decrease_layers.history["val_loss"]
val_precision = history_decrease_layers.history["val_precision_2"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("decrease_layers_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 16ms/step - loss: 0.1183 - accuracy: 0.9600 - precision_2: 0.9340
[0.11833204329013824, 0.9599999785423279, 0.9339622855186462]
Surprisingly, decreasing one convolution and pooling layers by resulted in a training accuracy of 0.9650 and a validation accuracy of 0.9650. The time it took to complete training and validation for 30 epochs was almost 3 minutes. The test performance is similar to the configuration with more layers; the accuracy with fewer layers is 0.9600, while the accuracy with more layers is 0.9650.
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model_increased_filters = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model_increased_filters.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="increase_filters_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_increased_filters = model_increased_filters.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 7s 35ms/step - loss: 0.6864 - accuracy: 0.5667 - precision_5: 0.5758 - val_loss: 0.5555 - val_accuracy: 0.5300 - val_precision_5: 1.0000 Epoch 2/30 150/150 [==============================] - 5s 34ms/step - loss: 0.5739 - accuracy: 0.7783 - precision_5: 0.7434 - val_loss: 0.3989 - val_accuracy: 0.9200 - val_precision_5: 0.8750 Epoch 3/30 150/150 [==============================] - 4s 25ms/step - loss: 0.4320 - accuracy: 0.8250 - precision_5: 0.7893 - val_loss: 0.4026 - val_accuracy: 0.8250 - val_precision_5: 0.7407 Epoch 4/30 150/150 [==============================] - 5s 32ms/step - loss: 0.3670 - accuracy: 0.8533 - precision_5: 0.8272 - val_loss: 0.2222 - val_accuracy: 0.9400 - val_precision_5: 0.9074 Epoch 5/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3517 - accuracy: 0.8600 - precision_5: 0.8418 - val_loss: 0.1955 - val_accuracy: 0.9450 - val_precision_5: 0.9238 Epoch 6/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2847 - accuracy: 0.9017 - precision_5: 0.8925 - val_loss: 0.2342 - val_accuracy: 0.9100 - val_precision_5: 0.8475 Epoch 7/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3516 - accuracy: 0.8567 - precision_5: 0.8223 - val_loss: 0.3013 - val_accuracy: 0.8700 - val_precision_5: 0.7937 Epoch 8/30 150/150 [==============================] - 5s 35ms/step - loss: 0.2920 - accuracy: 0.8917 - precision_5: 0.8730 - val_loss: 0.1861 - val_accuracy: 0.9400 - val_precision_5: 0.9000 Epoch 9/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2530 - accuracy: 0.9083 - precision_5: 0.8939 - val_loss: 0.1829 - val_accuracy: 0.9300 - val_precision_5: 0.8772 Epoch 10/30 150/150 [==============================] - 5s 34ms/step - loss: 0.2358 - accuracy: 0.9117 - precision_5: 0.8871 - val_loss: 0.1200 - val_accuracy: 0.9750 - val_precision_5: 0.9524 Epoch 11/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2333 - accuracy: 0.9317 - precision_5: 0.9164 - val_loss: 0.1762 - val_accuracy: 0.9300 - val_precision_5: 0.9778 Epoch 12/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2209 - accuracy: 0.9250 - precision_5: 0.9048 - val_loss: 0.2080 - val_accuracy: 0.9250 - val_precision_5: 1.0000 Epoch 13/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1672 - accuracy: 0.9333 - precision_5: 0.9194 - val_loss: 0.1530 - val_accuracy: 0.9400 - val_precision_5: 0.9000 Epoch 14/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1688 - accuracy: 0.9367 - precision_5: 0.9226 - val_loss: 0.0978 - val_accuracy: 0.9750 - val_precision_5: 0.9524 Epoch 15/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1536 - accuracy: 0.9433 - precision_5: 0.9290 - val_loss: 0.1072 - val_accuracy: 0.9650 - val_precision_5: 0.9429 Epoch 16/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1400 - accuracy: 0.9550 - precision_5: 0.9505 - val_loss: 0.1154 - val_accuracy: 0.9550 - val_precision_5: 0.9252 Epoch 17/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1864 - accuracy: 0.9400 - precision_5: 0.9342 - val_loss: 0.1474 - val_accuracy: 0.9500 - val_precision_5: 0.9091 Epoch 18/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1411 - accuracy: 0.9517 - precision_5: 0.9385 - val_loss: 0.1903 - val_accuracy: 0.9450 - val_precision_5: 1.0000 Epoch 19/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1708 - accuracy: 0.9517 - precision_5: 0.9414 - val_loss: 0.2120 - val_accuracy: 0.9100 - val_precision_5: 0.8534 Epoch 20/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1163 - accuracy: 0.9600 - precision_5: 0.9510 - val_loss: 0.2064 - val_accuracy: 0.9300 - val_precision_5: 0.8772 Epoch 21/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1155 - accuracy: 0.9700 - precision_5: 0.9608 - val_loss: 0.3247 - val_accuracy: 0.8700 - val_precision_5: 0.7937 Epoch 22/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1435 - accuracy: 0.9567 - precision_5: 0.9507 - val_loss: 0.1269 - val_accuracy: 0.9600 - val_precision_5: 0.9259 Epoch 23/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0887 - accuracy: 0.9767 - precision_5: 0.9673 - val_loss: 0.1428 - val_accuracy: 0.9500 - val_precision_5: 0.9091 Epoch 24/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0797 - accuracy: 0.9733 - precision_5: 0.9671 - val_loss: 0.2264 - val_accuracy: 0.9350 - val_precision_5: 0.8850 Epoch 25/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1477 - accuracy: 0.9533 - precision_5: 0.9416 - val_loss: 0.1820 - val_accuracy: 0.9150 - val_precision_5: 0.8609 Epoch 26/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1164 - accuracy: 0.9600 - precision_5: 0.9481 - val_loss: 0.1921 - val_accuracy: 0.9200 - val_precision_5: 0.8621 Epoch 27/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0966 - accuracy: 0.9700 - precision_5: 0.9608 - val_loss: 0.1543 - val_accuracy: 0.9500 - val_precision_5: 0.9167 Epoch 28/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0981 - accuracy: 0.9667 - precision_5: 0.9636 - val_loss: 0.0712 - val_accuracy: 0.9600 - val_precision_5: 0.9340 Epoch 29/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0729 - accuracy: 0.9817 - precision_5: 0.9769 - val_loss: 0.0907 - val_accuracy: 0.9750 - val_precision_5: 0.9524 Epoch 30/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0577 - accuracy: 0.9817 - precision_5: 0.9738 - val_loss: 0.1185 - val_accuracy: 0.9550 - val_precision_5: 0.9505
train_accuracy = history_increased_filters.history["accuracy"]
train_loss = history_increased_filters.history["loss"]
train_precision = history_increased_filters.history["precision_5"]
val_accuracy = history_increased_filters.history["val_accuracy"]
val_loss = history_increased_filters.history["val_loss"]
val_precision = history_increased_filters.history["val_precision_5"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("increase_filters_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 16ms/step - loss: 0.2045 - accuracy: 0.9400 - precision_5: 0.9000
[0.20448975265026093, 0.9399999976158142, 0.8999999761581421]
Surprisingly, increasing the number of convolution filters from 128 to 256 in two convolution layers resulted in a training accuracy of 0.98 and a validation accuracy of 0.9550. The time it took to complete training and validation for 30 epochs was close to 3 minutes. The test performance is same to the configuration with more filters; the accuracy with fewer filters is 0.94, while the accuracy with base configuration is 0.9650.
# Define the input shape and number of classes
input_shape = (100, 100, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model_decreased_image_size = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model_decreased_image_size.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="decrease_image_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_decreased_image_size = model_decreased_image_size.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 7s 34ms/step - loss: 0.6990 - accuracy: 0.5267 - precision_6: 0.5229 - val_loss: 0.6786 - val_accuracy: 0.6350 - val_precision_6: 0.9655 Epoch 2/30 150/150 [==============================] - 5s 33ms/step - loss: 0.6365 - accuracy: 0.6950 - precision_6: 0.6746 - val_loss: 0.4814 - val_accuracy: 0.8950 - val_precision_6: 0.8264 Epoch 3/30 150/150 [==============================] - 5s 33ms/step - loss: 0.5423 - accuracy: 0.7833 - precision_6: 0.7273 - val_loss: 0.3751 - val_accuracy: 0.8900 - val_precision_6: 0.8197 Epoch 4/30 150/150 [==============================] - 5s 33ms/step - loss: 0.4209 - accuracy: 0.8333 - precision_6: 0.7959 - val_loss: 0.1950 - val_accuracy: 0.9450 - val_precision_6: 0.9238 Epoch 5/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3331 - accuracy: 0.8650 - precision_6: 0.8349 - val_loss: 0.2097 - val_accuracy: 0.9400 - val_precision_6: 0.9583 Epoch 6/30 150/150 [==============================] - 4s 25ms/step - loss: 0.3599 - accuracy: 0.8600 - precision_6: 0.8333 - val_loss: 0.2302 - val_accuracy: 0.9250 - val_precision_6: 0.8696 Epoch 7/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3221 - accuracy: 0.8850 - precision_6: 0.8554 - val_loss: 0.1674 - val_accuracy: 0.9450 - val_precision_6: 0.9083 Epoch 8/30 150/150 [==============================] - 5s 35ms/step - loss: 0.2818 - accuracy: 0.9050 - precision_6: 0.8907 - val_loss: 0.1438 - val_accuracy: 0.9650 - val_precision_6: 0.9346 Epoch 9/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2689 - accuracy: 0.9133 - precision_6: 0.9052 - val_loss: 0.2027 - val_accuracy: 0.9150 - val_precision_6: 0.8547 Epoch 10/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2342 - accuracy: 0.9250 - precision_6: 0.9153 - val_loss: 0.1269 - val_accuracy: 0.9600 - val_precision_6: 0.9259 Epoch 11/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2197 - accuracy: 0.9183 - precision_6: 0.9115 - val_loss: 0.1042 - val_accuracy: 0.9750 - val_precision_6: 0.9524 Epoch 12/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1911 - accuracy: 0.9317 - precision_6: 0.9218 - val_loss: 0.0941 - val_accuracy: 0.9700 - val_precision_6: 0.9434 Epoch 13/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1821 - accuracy: 0.9333 - precision_6: 0.9221 - val_loss: 0.0890 - val_accuracy: 0.9650 - val_precision_6: 0.9697 Epoch 14/30 150/150 [==============================] - 5s 32ms/step - loss: 0.1875 - accuracy: 0.9317 - precision_6: 0.9164 - val_loss: 0.0655 - val_accuracy: 0.9900 - val_precision_6: 0.9804 Epoch 15/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1644 - accuracy: 0.9417 - precision_6: 0.9373 - val_loss: 0.0852 - val_accuracy: 0.9800 - val_precision_6: 0.9615 Epoch 16/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1683 - accuracy: 0.9483 - precision_6: 0.9353 - val_loss: 0.1528 - val_accuracy: 0.9350 - val_precision_6: 0.8850 Epoch 17/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1291 - accuracy: 0.9600 - precision_6: 0.9539 - val_loss: 0.0713 - val_accuracy: 0.9750 - val_precision_6: 0.9524 Epoch 18/30 150/150 [==============================] - 5s 35ms/step - loss: 0.1180 - accuracy: 0.9650 - precision_6: 0.9635 - val_loss: 0.0651 - val_accuracy: 0.9800 - val_precision_6: 0.9615 Epoch 19/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1227 - accuracy: 0.9567 - precision_6: 0.9536 - val_loss: 0.1022 - val_accuracy: 0.9600 - val_precision_6: 0.9259 Epoch 20/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1468 - accuracy: 0.9500 - precision_6: 0.9412 - val_loss: 0.0757 - val_accuracy: 0.9750 - val_precision_6: 0.9524 Epoch 21/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0926 - accuracy: 0.9750 - precision_6: 0.9672 - val_loss: 0.1660 - val_accuracy: 0.9400 - val_precision_6: 0.8929 Epoch 22/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0724 - accuracy: 0.9767 - precision_6: 0.9704 - val_loss: 0.0471 - val_accuracy: 0.9850 - val_precision_6: 0.9709 Epoch 23/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1340 - accuracy: 0.9600 - precision_6: 0.9570 - val_loss: 0.0758 - val_accuracy: 0.9700 - val_precision_6: 0.9434 Epoch 24/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0853 - accuracy: 0.9733 - precision_6: 0.9702 - val_loss: 0.1155 - val_accuracy: 0.9600 - val_precision_6: 0.9259 Epoch 25/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1207 - accuracy: 0.9583 - precision_6: 0.9479 - val_loss: 0.0936 - val_accuracy: 0.9650 - val_precision_6: 0.9346 Epoch 26/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0702 - accuracy: 0.9750 - precision_6: 0.9672 - val_loss: 0.0794 - val_accuracy: 0.9750 - val_precision_6: 0.9524 Epoch 27/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0644 - accuracy: 0.9817 - precision_6: 0.9769 - val_loss: 0.1411 - val_accuracy: 0.9700 - val_precision_6: 0.9434 Epoch 28/30 150/150 [==============================] - 4s 27ms/step - loss: 0.0399 - accuracy: 0.9867 - precision_6: 0.9834 - val_loss: 0.1261 - val_accuracy: 0.9700 - val_precision_6: 0.9434 Epoch 29/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1526 - accuracy: 0.9500 - precision_6: 0.9441 - val_loss: 0.1484 - val_accuracy: 0.9450 - val_precision_6: 0.9890 Epoch 30/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0874 - accuracy: 0.9717 - precision_6: 0.9670 - val_loss: 0.0700 - val_accuracy: 0.9700 - val_precision_6: 0.9519
train_accuracy = history_decreased_image_size.history["accuracy"]
train_loss = history_decreased_image_size.history["loss"]
train_precision = history_decreased_image_size.history["precision_6"]
val_accuracy = history_decreased_image_size.history["val_accuracy"]
val_loss = history_decreased_image_size.history["val_loss"]
val_precision = history_decreased_image_size.history["val_precision_6"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("decrease_image_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 17ms/step - loss: 0.1472 - accuracy: 0.9400 - precision_6: 0.9074
[0.14721837639808655, 0.9399999976158142, 0.9074074029922485]
Decreasing the size of input images by almost 40% resulted in a training accuracy of 0.9717 and a validation accuracy of 0.97. The time it took to complete training and validation for 30 epochs was close to 3 minutes. The test performance is identical to the configuration with larger input sizes; the accuracy with the smaller image size is 0.94, while the accuracy with the larger image size is 0.9650.
# Let's load the best performing model
best_model = keras.models.load_model("base_model_checkpoint_filepath")
# Rotation Augmentation
data_augmentation = keras.Sequential(
[layers.RandomRotation(0.2)] # 20 degrees
)
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = data_augmentation(inputs)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model_rotation_augmentation = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model_rotation_augmentation.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="rotation_augmentation_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_rotation_augmentation = model_rotation_augmentation.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 7s 35ms/step - loss: 0.6799 - accuracy: 0.5700 - precision_10: 0.5714 - val_loss: 0.4949 - val_accuracy: 0.7950 - val_precision_10: 0.9538 Epoch 2/30 150/150 [==============================] - 5s 36ms/step - loss: 0.5688 - accuracy: 0.7833 - precision_10: 0.7560 - val_loss: 0.3203 - val_accuracy: 0.9050 - val_precision_10: 0.8403 Epoch 3/30 150/150 [==============================] - 5s 33ms/step - loss: 0.4012 - accuracy: 0.8533 - precision_10: 0.8232 - val_loss: 0.1926 - val_accuracy: 0.9300 - val_precision_10: 0.8772 Epoch 4/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3607 - accuracy: 0.8817 - precision_10: 0.8523 - val_loss: 0.2017 - val_accuracy: 0.9550 - val_precision_10: 0.9505 Epoch 5/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3452 - accuracy: 0.8667 - precision_10: 0.8395 - val_loss: 0.2345 - val_accuracy: 0.9200 - val_precision_10: 0.8621 Epoch 6/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2876 - accuracy: 0.8883 - precision_10: 0.8698 - val_loss: 0.1944 - val_accuracy: 0.9200 - val_precision_10: 0.8621 Epoch 7/30 150/150 [==============================] - 5s 32ms/step - loss: 0.2761 - accuracy: 0.9017 - precision_10: 0.8801 - val_loss: 0.1613 - val_accuracy: 0.9400 - val_precision_10: 0.8929 Epoch 8/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2590 - accuracy: 0.9100 - precision_10: 0.9020 - val_loss: 0.1274 - val_accuracy: 0.9500 - val_precision_10: 0.9592 Epoch 9/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2378 - accuracy: 0.9067 - precision_10: 0.8910 - val_loss: 0.1353 - val_accuracy: 0.9650 - val_precision_10: 0.9346 Epoch 10/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2491 - accuracy: 0.9167 - precision_10: 0.8981 - val_loss: 0.1748 - val_accuracy: 0.9550 - val_precision_10: 0.9174 Epoch 11/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2141 - accuracy: 0.9133 - precision_10: 0.9052 - val_loss: 0.1438 - val_accuracy: 0.9550 - val_precision_10: 0.9174 Epoch 12/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2692 - accuracy: 0.9083 - precision_10: 0.8914 - val_loss: 0.2053 - val_accuracy: 0.9300 - val_precision_10: 0.8772 Epoch 13/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2517 - accuracy: 0.9150 - precision_10: 0.8978 - val_loss: 0.1219 - val_accuracy: 0.9650 - val_precision_10: 0.9346 Epoch 14/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1828 - accuracy: 0.9350 - precision_10: 0.9307 - val_loss: 0.1498 - val_accuracy: 0.9200 - val_precision_10: 0.8621 Epoch 15/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1611 - accuracy: 0.9467 - precision_10: 0.9379 - val_loss: 0.1819 - val_accuracy: 0.9100 - val_precision_10: 0.8475 Epoch 16/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1680 - accuracy: 0.9450 - precision_10: 0.9349 - val_loss: 0.1450 - val_accuracy: 0.9250 - val_precision_10: 0.8696 Epoch 17/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1679 - accuracy: 0.9450 - precision_10: 0.9495 - val_loss: 0.0814 - val_accuracy: 0.9800 - val_precision_10: 0.9615 Epoch 18/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1086 - accuracy: 0.9617 - precision_10: 0.9541 - val_loss: 0.1214 - val_accuracy: 0.9550 - val_precision_10: 0.9174 Epoch 19/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1262 - accuracy: 0.9617 - precision_10: 0.9601 - val_loss: 0.0959 - val_accuracy: 0.9650 - val_precision_10: 0.9346 Epoch 20/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1431 - accuracy: 0.9500 - precision_10: 0.9383 - val_loss: 0.0868 - val_accuracy: 0.9850 - val_precision_10: 0.9899 Epoch 21/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1037 - accuracy: 0.9667 - precision_10: 0.9605 - val_loss: 0.0792 - val_accuracy: 0.9700 - val_precision_10: 0.9434 Epoch 22/30 150/150 [==============================] - 5s 36ms/step - loss: 0.0931 - accuracy: 0.9733 - precision_10: 0.9671 - val_loss: 0.0538 - val_accuracy: 0.9800 - val_precision_10: 0.9615 Epoch 23/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1330 - accuracy: 0.9583 - precision_10: 0.9538 - val_loss: 0.1151 - val_accuracy: 0.9650 - val_precision_10: 0.9429 Epoch 24/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1490 - accuracy: 0.9450 - precision_10: 0.9377 - val_loss: 0.0766 - val_accuracy: 0.9750 - val_precision_10: 0.9524 Epoch 25/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0812 - accuracy: 0.9800 - precision_10: 0.9768 - val_loss: 0.0490 - val_accuracy: 0.9800 - val_precision_10: 0.9706 Epoch 26/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0716 - accuracy: 0.9733 - precision_10: 0.9671 - val_loss: 0.1881 - val_accuracy: 0.9300 - val_precision_10: 0.8772 Epoch 27/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1169 - accuracy: 0.9583 - precision_10: 0.9479 - val_loss: 0.0515 - val_accuracy: 0.9850 - val_precision_10: 0.9709 Epoch 28/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0719 - accuracy: 0.9767 - precision_10: 0.9704 - val_loss: 0.0833 - val_accuracy: 0.9750 - val_precision_10: 0.9524 Epoch 29/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0514 - accuracy: 0.9833 - precision_10: 0.9801 - val_loss: 0.0710 - val_accuracy: 0.9850 - val_precision_10: 0.9899 Epoch 30/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0599 - accuracy: 0.9800 - precision_10: 0.9832 - val_loss: 0.0588 - val_accuracy: 0.9800 - val_precision_10: 0.9615
train_accuracy = history_rotation_augmentation.history["accuracy"]
train_loss = history_rotation_augmentation.history["loss"]
train_precision = history_rotation_augmentation.history["precision_10"]
val_accuracy = history_rotation_augmentation.history["val_accuracy"]
val_loss = history_rotation_augmentation.history["val_loss"]
val_precision = history_rotation_augmentation.history["val_precision_10"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("rotation_augmentation_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 16ms/step - loss: 0.0988 - accuracy: 0.9800 - precision_10: 0.9615
[0.09880392998456955, 0.9800000190734863, 0.9615384340286255]
Applying the rotation augmentation resulted in a training accuracy of 0.98 and a validation accuracy of 0.98. The time it took to complete training and validation for 30 epochs was close to 3 minutes. The test performance improved compared to the base configuration; the accuracy with rotation augmentation is 0.98, while the accuracy with the base configuration is 0.9650.
data_augmentation = keras.Sequential(
[layers.RandomTranslation(width_factor=0.2, height_factor=0.0)] # 20% width shift
)
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = data_augmentation(inputs)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model_width_shift_augmentation = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model_width_shift_augmentation.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="width_shift_augmentation_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_width_shift_augmentation = model_width_shift_augmentation.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 7s 35ms/step - loss: 0.6653 - accuracy: 0.6333 - precision_11: 0.6869 - val_loss: 0.5129 - val_accuracy: 0.8000 - val_precision_11: 0.7143 Epoch 2/30 150/150 [==============================] - 5s 33ms/step - loss: 0.5834 - accuracy: 0.7433 - precision_11: 0.6984 - val_loss: 0.2870 - val_accuracy: 0.9150 - val_precision_11: 0.8739 Epoch 3/30 150/150 [==============================] - 6s 37ms/step - loss: 0.4163 - accuracy: 0.8433 - precision_11: 0.8140 - val_loss: 0.2449 - val_accuracy: 0.9400 - val_precision_11: 0.9074 Epoch 4/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3795 - accuracy: 0.8600 - precision_11: 0.8253 - val_loss: 0.3664 - val_accuracy: 0.8500 - val_precision_11: 0.7692 Epoch 5/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3394 - accuracy: 0.8717 - precision_11: 0.8474 - val_loss: 0.1726 - val_accuracy: 0.9500 - val_precision_11: 0.9091 Epoch 6/30 150/150 [==============================] - 4s 26ms/step - loss: 0.3058 - accuracy: 0.8850 - precision_11: 0.8667 - val_loss: 0.1776 - val_accuracy: 0.9450 - val_precision_11: 0.9009 Epoch 7/30 150/150 [==============================] - 4s 25ms/step - loss: 0.3023 - accuracy: 0.8850 - precision_11: 0.8598 - val_loss: 0.1908 - val_accuracy: 0.9500 - val_precision_11: 0.9500 Epoch 8/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2626 - accuracy: 0.9083 - precision_11: 0.9016 - val_loss: 0.2427 - val_accuracy: 0.9100 - val_precision_11: 0.8475 Epoch 9/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2548 - accuracy: 0.8883 - precision_11: 0.8770 - val_loss: 0.1412 - val_accuracy: 0.9350 - val_precision_11: 0.9485 Epoch 10/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2344 - accuracy: 0.9150 - precision_11: 0.8927 - val_loss: 0.1603 - val_accuracy: 0.9450 - val_precision_11: 0.9009 Epoch 11/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2203 - accuracy: 0.9133 - precision_11: 0.9026 - val_loss: 0.1477 - val_accuracy: 0.9500 - val_precision_11: 0.9500 Epoch 12/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1965 - accuracy: 0.9300 - precision_11: 0.9243 - val_loss: 0.1025 - val_accuracy: 0.9750 - val_precision_11: 0.9612 Epoch 13/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2100 - accuracy: 0.9267 - precision_11: 0.9183 - val_loss: 0.1290 - val_accuracy: 0.9550 - val_precision_11: 0.9252 Epoch 14/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1787 - accuracy: 0.9367 - precision_11: 0.9309 - val_loss: 0.1239 - val_accuracy: 0.9600 - val_precision_11: 0.9259 Epoch 15/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1877 - accuracy: 0.9367 - precision_11: 0.9338 - val_loss: 0.1989 - val_accuracy: 0.9300 - val_precision_11: 0.8772 Epoch 16/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1668 - accuracy: 0.9383 - precision_11: 0.9283 - val_loss: 0.1116 - val_accuracy: 0.9600 - val_precision_11: 0.9259 Epoch 17/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2327 - accuracy: 0.9167 - precision_11: 0.9058 - val_loss: 0.2092 - val_accuracy: 0.8900 - val_precision_11: 0.8197 Epoch 18/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1385 - accuracy: 0.9433 - precision_11: 0.9375 - val_loss: 0.1862 - val_accuracy: 0.9250 - val_precision_11: 0.8696 Epoch 19/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1621 - accuracy: 0.9383 - precision_11: 0.9340 - val_loss: 0.1207 - val_accuracy: 0.9500 - val_precision_11: 0.9091 Epoch 20/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1253 - accuracy: 0.9483 - precision_11: 0.9468 - val_loss: 0.3504 - val_accuracy: 0.8950 - val_precision_11: 0.8264 Epoch 21/30 150/150 [==============================] - 5s 32ms/step - loss: 0.1124 - accuracy: 0.9550 - precision_11: 0.9475 - val_loss: 0.0922 - val_accuracy: 0.9650 - val_precision_11: 0.9346 Epoch 22/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0881 - accuracy: 0.9650 - precision_11: 0.9666 - val_loss: 0.0729 - val_accuracy: 0.9700 - val_precision_11: 0.9434 Epoch 23/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0860 - accuracy: 0.9700 - precision_11: 0.9608 - val_loss: 0.0690 - val_accuracy: 0.9800 - val_precision_11: 0.9800 Epoch 24/30 150/150 [==============================] - 5s 36ms/step - loss: 0.1141 - accuracy: 0.9600 - precision_11: 0.9510 - val_loss: 0.0374 - val_accuracy: 0.9900 - val_precision_11: 0.9804 Epoch 25/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0903 - accuracy: 0.9700 - precision_11: 0.9638 - val_loss: 0.0551 - val_accuracy: 0.9900 - val_precision_11: 0.9804 Epoch 26/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0595 - accuracy: 0.9800 - precision_11: 0.9768 - val_loss: 0.0611 - val_accuracy: 0.9700 - val_precision_11: 0.9434 Epoch 27/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1693 - accuracy: 0.9483 - precision_11: 0.9439 - val_loss: 0.0984 - val_accuracy: 0.9600 - val_precision_11: 0.9423 Epoch 28/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0903 - accuracy: 0.9617 - precision_11: 0.9663 - val_loss: 0.0678 - val_accuracy: 0.9700 - val_precision_11: 0.9434 Epoch 29/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0739 - accuracy: 0.9717 - precision_11: 0.9639 - val_loss: 0.0605 - val_accuracy: 0.9750 - val_precision_11: 0.9524 Epoch 30/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0402 - accuracy: 0.9883 - precision_11: 0.9835 - val_loss: 0.0720 - val_accuracy: 0.9800 - val_precision_11: 0.9706
train_accuracy = history_width_shift_augmentation.history["accuracy"]
train_loss = history_width_shift_augmentation.history["loss"]
train_precision = history_width_shift_augmentation.history["precision_11"]
val_accuracy = history_width_shift_augmentation.history["val_accuracy"]
val_loss = history_width_shift_augmentation.history["val_loss"]
val_precision = history_width_shift_augmentation.history["val_precision_11"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("width_shift_augmentation_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 17ms/step - loss: 0.1022 - accuracy: 0.9750 - precision_11: 0.9612
[0.10224905610084534, 0.9750000238418579, 0.9611650705337524]
Applying the width shift augmentation resulted in a training accuracy of 0.9883 and a validation accuracy of 0.98. The time it took to complete training and validation for 30 epochs was close to 3 minutes. The test performance improved compared to the base configuration; the accuracy with width shift augmentation is 0.9750, while the accuracy with the base configuration is 0.9650.
data_augmentation = keras.Sequential(
[layers.RandomBrightness(0.5)] # Range [0.5, 1.5]
)
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = data_augmentation(inputs)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
brightness_augmentation = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
brightness_augmentation.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="brightness_augmentation_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_brightness_augmentation = brightness_augmentation.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 7s 34ms/step - loss: 0.6568 - accuracy: 0.5850 - precision_13: 0.6783 - val_loss: 0.5226 - val_accuracy: 0.8600 - val_precision_13: 0.7857 Epoch 2/30 150/150 [==============================] - 5s 35ms/step - loss: 0.4526 - accuracy: 0.8083 - precision_13: 0.7713 - val_loss: 0.2636 - val_accuracy: 0.9350 - val_precision_13: 0.9394 Epoch 3/30 150/150 [==============================] - 4s 27ms/step - loss: 0.3716 - accuracy: 0.8833 - precision_13: 0.8616 - val_loss: 0.6083 - val_accuracy: 0.7100 - val_precision_13: 0.6329 Epoch 4/30 150/150 [==============================] - 5s 34ms/step - loss: 0.3571 - accuracy: 0.8650 - precision_13: 0.8454 - val_loss: 0.1704 - val_accuracy: 0.9400 - val_precision_13: 0.8929 Epoch 5/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3074 - accuracy: 0.8933 - precision_13: 0.8687 - val_loss: 0.1463 - val_accuracy: 0.9450 - val_precision_13: 0.9083 Epoch 6/30 150/150 [==============================] - 6s 37ms/step - loss: 0.2651 - accuracy: 0.9200 - precision_13: 0.9091 - val_loss: 0.1364 - val_accuracy: 0.9500 - val_precision_13: 0.9167 Epoch 7/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2530 - accuracy: 0.9083 - precision_13: 0.8889 - val_loss: 0.1554 - val_accuracy: 0.9400 - val_precision_13: 0.8929 Epoch 8/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2539 - accuracy: 0.9067 - precision_13: 0.8910 - val_loss: 0.1496 - val_accuracy: 0.9550 - val_precision_13: 0.9252 Epoch 9/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2335 - accuracy: 0.9183 - precision_13: 0.9035 - val_loss: 0.1596 - val_accuracy: 0.9450 - val_precision_13: 0.9009 Epoch 10/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2253 - accuracy: 0.9300 - precision_13: 0.9161 - val_loss: 0.1076 - val_accuracy: 0.9700 - val_precision_13: 0.9519 Epoch 11/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1969 - accuracy: 0.9367 - precision_13: 0.9309 - val_loss: 0.1759 - val_accuracy: 0.9400 - val_precision_13: 0.8929 Epoch 12/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2069 - accuracy: 0.9217 - precision_13: 0.9068 - val_loss: 0.1215 - val_accuracy: 0.9750 - val_precision_13: 0.9524 Epoch 13/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1560 - accuracy: 0.9533 - precision_13: 0.9503 - val_loss: 0.0956 - val_accuracy: 0.9600 - val_precision_13: 0.9259 Epoch 14/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1474 - accuracy: 0.9417 - precision_13: 0.9402 - val_loss: 0.3825 - val_accuracy: 0.8700 - val_precision_13: 0.7937 Epoch 15/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1425 - accuracy: 0.9483 - precision_13: 0.9381 - val_loss: 0.1527 - val_accuracy: 0.9400 - val_precision_13: 0.8929 Epoch 16/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1419 - accuracy: 0.9433 - precision_13: 0.9404 - val_loss: 0.0937 - val_accuracy: 0.9700 - val_precision_13: 0.9608 Epoch 17/30 150/150 [==============================] - 5s 32ms/step - loss: 0.1576 - accuracy: 0.9450 - precision_13: 0.9406 - val_loss: 0.0927 - val_accuracy: 0.9800 - val_precision_13: 0.9615 Epoch 18/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0921 - accuracy: 0.9667 - precision_13: 0.9605 - val_loss: 0.1536 - val_accuracy: 0.9650 - val_precision_13: 0.9346 Epoch 19/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1498 - accuracy: 0.9600 - precision_13: 0.9481 - val_loss: 0.1359 - val_accuracy: 0.9400 - val_precision_13: 0.8929 Epoch 20/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0816 - accuracy: 0.9733 - precision_13: 0.9641 - val_loss: 0.1287 - val_accuracy: 0.9450 - val_precision_13: 0.9009 Epoch 21/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1158 - accuracy: 0.9550 - precision_13: 0.9505 - val_loss: 0.1049 - val_accuracy: 0.9600 - val_precision_13: 0.9259 Epoch 22/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0804 - accuracy: 0.9717 - precision_13: 0.9639 - val_loss: 0.1589 - val_accuracy: 0.9500 - val_precision_13: 0.9091 Epoch 23/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0979 - accuracy: 0.9633 - precision_13: 0.9572 - val_loss: 0.1458 - val_accuracy: 0.9500 - val_precision_13: 0.9091 Epoch 24/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0656 - accuracy: 0.9817 - precision_13: 0.9738 - val_loss: 0.1595 - val_accuracy: 0.9300 - val_precision_13: 0.8772 Epoch 25/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0470 - accuracy: 0.9867 - precision_13: 0.9803 - val_loss: 0.1340 - val_accuracy: 0.9550 - val_precision_13: 0.9505 Epoch 26/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0389 - accuracy: 0.9850 - precision_13: 0.9866 - val_loss: 0.0884 - val_accuracy: 0.9600 - val_precision_13: 0.9259 Epoch 27/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0275 - accuracy: 0.9917 - precision_13: 0.9900 - val_loss: 0.1583 - val_accuracy: 0.9500 - val_precision_13: 0.9091 Epoch 28/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0428 - accuracy: 0.9817 - precision_13: 0.9801 - val_loss: 0.1698 - val_accuracy: 0.9650 - val_precision_13: 0.9346 Epoch 29/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2470 - accuracy: 0.9367 - precision_13: 0.9199 - val_loss: 0.1513 - val_accuracy: 0.9400 - val_precision_13: 0.8929 Epoch 30/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1679 - accuracy: 0.9433 - precision_13: 0.9404 - val_loss: 0.1189 - val_accuracy: 0.9450 - val_precision_13: 0.9009
train_accuracy = history_brightness_augmentation.history["accuracy"]
train_loss = history_brightness_augmentation.history["loss"]
train_precision = history_brightness_augmentation.history["precision_13"]
val_accuracy = history_brightness_augmentation.history["val_accuracy"]
val_loss = history_brightness_augmentation.history["val_loss"]
val_precision = history_brightness_augmentation.history["val_precision_13"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("brightness_augmentation_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 16ms/step - loss: 0.1735 - accuracy: 0.9550 - precision_13: 0.9174
[0.17353056371212006, 0.9549999833106995, 0.9174311757087708]
Applying the brightness augmentation resulted in a training accuracy of 0.98 and a validation accuracy of 0.9650. The time it took to complete training and validation for 30 epochs was close to 3 minutes. The test performance is almost similar to the base configuration; the accuracy with brightness augmentation is 0.9550, while the accuracy with the base configuration is 0.9650.
data_augmentation = keras.Sequential(
[layers.RandomFlip("horizontal")]
)
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = data_augmentation(inputs)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
horizontal_flip_augmentation = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
horizontal_flip_augmentation.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="horizontal_flip_augmentation_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_flip_augmentation = horizontal_flip_augmentation.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 8s 35ms/step - loss: 0.6728 - accuracy: 0.5633 - precision_14: 0.5913 - val_loss: 0.6970 - val_accuracy: 0.5000 - val_precision_14: 0.5000 Epoch 2/30 150/150 [==============================] - 5s 33ms/step - loss: 0.5717 - accuracy: 0.7083 - precision_14: 0.6844 - val_loss: 0.3000 - val_accuracy: 0.8900 - val_precision_14: 0.9149 Epoch 3/30 150/150 [==============================] - 5s 34ms/step - loss: 0.5321 - accuracy: 0.7767 - precision_14: 0.7385 - val_loss: 0.2666 - val_accuracy: 0.8950 - val_precision_14: 0.9072 Epoch 4/30 150/150 [==============================] - 4s 26ms/step - loss: 0.4134 - accuracy: 0.8400 - precision_14: 0.8000 - val_loss: 0.3490 - val_accuracy: 0.8750 - val_precision_14: 0.8000 Epoch 5/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3834 - accuracy: 0.8467 - precision_14: 0.8171 - val_loss: 0.1897 - val_accuracy: 0.9350 - val_precision_14: 0.9307 Epoch 6/30 150/150 [==============================] - 5s 35ms/step - loss: 0.3161 - accuracy: 0.8867 - precision_14: 0.8648 - val_loss: 0.1878 - val_accuracy: 0.9450 - val_precision_14: 0.9159 Epoch 7/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2970 - accuracy: 0.8800 - precision_14: 0.8631 - val_loss: 0.1967 - val_accuracy: 0.9400 - val_precision_14: 0.9074 Epoch 8/30 150/150 [==============================] - 5s 32ms/step - loss: 0.2950 - accuracy: 0.8817 - precision_14: 0.8706 - val_loss: 0.1743 - val_accuracy: 0.9500 - val_precision_14: 0.9091 Epoch 9/30 150/150 [==============================] - 5s 36ms/step - loss: 0.2661 - accuracy: 0.9100 - precision_14: 0.8917 - val_loss: 0.1414 - val_accuracy: 0.9500 - val_precision_14: 0.9091 Epoch 10/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2418 - accuracy: 0.9200 - precision_14: 0.9091 - val_loss: 0.1000 - val_accuracy: 0.9700 - val_precision_14: 0.9519 Epoch 11/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2166 - accuracy: 0.9200 - precision_14: 0.9065 - val_loss: 0.1063 - val_accuracy: 0.9600 - val_precision_14: 0.9259 Epoch 12/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2280 - accuracy: 0.9133 - precision_14: 0.9106 - val_loss: 0.1722 - val_accuracy: 0.9250 - val_precision_14: 0.8696 Epoch 13/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2223 - accuracy: 0.9150 - precision_14: 0.8952 - val_loss: 0.1702 - val_accuracy: 0.9700 - val_precision_14: 0.9434 Epoch 14/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1891 - accuracy: 0.9350 - precision_14: 0.9251 - val_loss: 0.0799 - val_accuracy: 0.9900 - val_precision_14: 0.9804 Epoch 15/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1643 - accuracy: 0.9367 - precision_14: 0.9281 - val_loss: 0.2004 - val_accuracy: 0.9250 - val_precision_14: 0.8696 Epoch 16/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1885 - accuracy: 0.9350 - precision_14: 0.9196 - val_loss: 0.0881 - val_accuracy: 0.9850 - val_precision_14: 0.9709 Epoch 17/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1615 - accuracy: 0.9500 - precision_14: 0.9412 - val_loss: 0.0971 - val_accuracy: 0.9650 - val_precision_14: 0.9346 Epoch 18/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1165 - accuracy: 0.9567 - precision_14: 0.9536 - val_loss: 0.1474 - val_accuracy: 0.9400 - val_precision_14: 0.8929 Epoch 19/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1565 - accuracy: 0.9467 - precision_14: 0.9379 - val_loss: 0.1787 - val_accuracy: 0.9350 - val_precision_14: 0.8850 Epoch 20/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1015 - accuracy: 0.9600 - precision_14: 0.9539 - val_loss: 0.1502 - val_accuracy: 0.9350 - val_precision_14: 0.8850 Epoch 21/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1281 - accuracy: 0.9617 - precision_14: 0.9601 - val_loss: 0.0896 - val_accuracy: 0.9850 - val_precision_14: 0.9709 Epoch 22/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1482 - accuracy: 0.9483 - precision_14: 0.9381 - val_loss: 0.1713 - val_accuracy: 0.9350 - val_precision_14: 0.8850 Epoch 23/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1040 - accuracy: 0.9683 - precision_14: 0.9607 - val_loss: 0.1518 - val_accuracy: 0.9400 - val_precision_14: 0.8929 Epoch 24/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0977 - accuracy: 0.9567 - precision_14: 0.9536 - val_loss: 0.2124 - val_accuracy: 0.9250 - val_precision_14: 0.8696 Epoch 25/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0943 - accuracy: 0.9683 - precision_14: 0.9607 - val_loss: 0.3347 - val_accuracy: 0.9300 - val_precision_14: 0.8772 Epoch 26/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0942 - accuracy: 0.9617 - precision_14: 0.9601 - val_loss: 0.0709 - val_accuracy: 0.9800 - val_precision_14: 0.9706 Epoch 27/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0593 - accuracy: 0.9783 - precision_14: 0.9736 - val_loss: 0.1059 - val_accuracy: 0.9600 - val_precision_14: 0.9259 Epoch 28/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0635 - accuracy: 0.9767 - precision_14: 0.9704 - val_loss: 0.2104 - val_accuracy: 0.9200 - val_precision_14: 0.8621 Epoch 29/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0588 - accuracy: 0.9800 - precision_14: 0.9768 - val_loss: 0.2481 - val_accuracy: 0.9250 - val_precision_14: 0.8696 Epoch 30/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0924 - accuracy: 0.9733 - precision_14: 0.9702 - val_loss: 0.1661 - val_accuracy: 0.9400 - val_precision_14: 0.9000
train_accuracy = history_flip_augmentation.history["accuracy"]
train_loss = history_flip_augmentation.history["loss"]
train_precision = history_flip_augmentation.history["precision_14"]
val_accuracy = history_flip_augmentation.history["val_accuracy"]
val_loss = history_flip_augmentation.history["val_loss"]
val_precision = history_flip_augmentation.history["val_precision_14"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("horizontal_flip_augmentation_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 17ms/step - loss: 0.1305 - accuracy: 0.9650 - precision_14: 0.9346
[0.13046668469905853, 0.9649999737739563, 0.9345794320106506]
Applying the horizontal flip resulted in a training accuracy of 0.9736 and a validation accuracy of 0.96. The time it took to complete training and validation for 30 epochs was close to 3 minutes. The test performance is similar to the base configuration; the accuracy with horizontal flip is 0.9650, while the accuracy with the base configuration is 0.9650.
data_augmentation = keras.Sequential(
[
layers.RandomRotation(0.2), # 20 degrees
layers.RandomTranslation(width_factor=0.2, height_factor=0.0), # 20% shift
layers.RandomBrightness(0.5), # Brightness variation
layers.RandomFlip("horizontal") # Horizontal flip
]
)
# Define the input shape and number of classes
input_shape = (150, 150, 3)
num_classes = 2
# Start defining the model
inputs = keras.Input(shape=input_shape)
x = data_augmentation(inputs)
x = layers.Conv2D(32, 3, padding='same', activation='relu')(inputs)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(64, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(128, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Adding a couple more Conv2D and MaxPooling2D layers
x = layers.Conv2D(256, 3, padding='same', activation='relu')(x)
x = layers.MaxPooling2D(pool_size=2)(x)
# Global Average Pooling followed by the classifier
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x) # Common dropout rate for regularization
# Output layer
outputs = layers.Dense(1, activation='sigmoid')(x)
# Finalize the model
model_combined_augmentation = keras.Model(inputs=inputs, outputs=outputs)
# Let's compile the CNN model using binary cross_entropy as loss function and adam as optimizer
model_combined_augmentation.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy', keras.metrics.Precision()])
# Let's define the callbacks for Model saving and Early stopping
cb_check = keras.callbacks.ModelCheckpoint(
filepath="combined_augmentation_checkpoint_filepath",
save_best_only=True,
monitor="val_loss")
cb_early = keras.callbacks.EarlyStopping(
monitor="val_loss",
patience=30
)
# Let's train and validate model on the training and validation data
history_combined_augmentation = model_combined_augmentation.fit(train_generator, validation_data = valid_generator, epochs = 30, verbose = 1, batch_size = 8, callbacks = [cb_check, cb_early])
Epoch 1/30 150/150 [==============================] - 8s 38ms/step - loss: 0.6796 - accuracy: 0.5783 - precision_15: 0.5770 - val_loss: 0.6771 - val_accuracy: 0.6100 - val_precision_15: 0.5618 Epoch 2/30 150/150 [==============================] - 5s 33ms/step - loss: 0.5650 - accuracy: 0.7267 - precision_15: 0.7125 - val_loss: 0.2966 - val_accuracy: 0.8950 - val_precision_15: 0.8319 Epoch 3/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3897 - accuracy: 0.8600 - precision_15: 0.8253 - val_loss: 0.2114 - val_accuracy: 0.9400 - val_precision_15: 0.9074 Epoch 4/30 150/150 [==============================] - 5s 33ms/step - loss: 0.4412 - accuracy: 0.8367 - precision_15: 0.7953 - val_loss: 0.2100 - val_accuracy: 0.9200 - val_precision_15: 0.8684 Epoch 5/30 150/150 [==============================] - 5s 33ms/step - loss: 0.3093 - accuracy: 0.8850 - precision_15: 0.8598 - val_loss: 0.1798 - val_accuracy: 0.9450 - val_precision_15: 0.9083 Epoch 6/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2964 - accuracy: 0.8917 - precision_15: 0.8660 - val_loss: 0.1481 - val_accuracy: 0.9700 - val_precision_15: 0.9519 Epoch 7/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2501 - accuracy: 0.9083 - precision_15: 0.8964 - val_loss: 0.1758 - val_accuracy: 0.9300 - val_precision_15: 0.8772 Epoch 8/30 150/150 [==============================] - 5s 33ms/step - loss: 0.2555 - accuracy: 0.9083 - precision_15: 0.8914 - val_loss: 0.1367 - val_accuracy: 0.9700 - val_precision_15: 0.9608 Epoch 9/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2698 - accuracy: 0.9067 - precision_15: 0.9040 - val_loss: 0.1469 - val_accuracy: 0.9550 - val_precision_15: 0.9174 Epoch 10/30 150/150 [==============================] - 4s 26ms/step - loss: 0.2164 - accuracy: 0.9167 - precision_15: 0.9085 - val_loss: 0.1594 - val_accuracy: 0.9500 - val_precision_15: 0.9091 Epoch 11/30 150/150 [==============================] - 4s 25ms/step - loss: 0.2076 - accuracy: 0.9233 - precision_15: 0.9178 - val_loss: 0.1383 - val_accuracy: 0.9600 - val_precision_15: 0.9259 Epoch 12/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1728 - accuracy: 0.9317 - precision_15: 0.9218 - val_loss: 0.1440 - val_accuracy: 0.9300 - val_precision_15: 0.9674 Epoch 13/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1903 - accuracy: 0.9300 - precision_15: 0.9216 - val_loss: 0.1217 - val_accuracy: 0.9650 - val_precision_15: 0.9346 Epoch 14/30 150/150 [==============================] - 6s 37ms/step - loss: 0.1673 - accuracy: 0.9450 - precision_15: 0.9406 - val_loss: 0.1150 - val_accuracy: 0.9600 - val_precision_15: 0.9259 Epoch 15/30 150/150 [==============================] - 5s 32ms/step - loss: 0.1647 - accuracy: 0.9433 - precision_15: 0.9290 - val_loss: 0.1109 - val_accuracy: 0.9800 - val_precision_15: 0.9615 Epoch 16/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1861 - accuracy: 0.9333 - precision_15: 0.9221 - val_loss: 0.0998 - val_accuracy: 0.9650 - val_precision_15: 0.9429 Epoch 17/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1376 - accuracy: 0.9483 - precision_15: 0.9439 - val_loss: 0.1044 - val_accuracy: 0.9650 - val_precision_15: 0.9346 Epoch 18/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1153 - accuracy: 0.9633 - precision_15: 0.9603 - val_loss: 0.0943 - val_accuracy: 0.9700 - val_precision_15: 0.9434 Epoch 19/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1092 - accuracy: 0.9650 - precision_15: 0.9666 - val_loss: 0.1381 - val_accuracy: 0.9450 - val_precision_15: 0.9009 Epoch 20/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1006 - accuracy: 0.9650 - precision_15: 0.9604 - val_loss: 0.1238 - val_accuracy: 0.9650 - val_precision_15: 0.9429 Epoch 21/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0901 - accuracy: 0.9750 - precision_15: 0.9703 - val_loss: 0.1862 - val_accuracy: 0.9300 - val_precision_15: 0.9886 Epoch 22/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1157 - accuracy: 0.9650 - precision_15: 0.9666 - val_loss: 0.1546 - val_accuracy: 0.9600 - val_precision_15: 0.9259 Epoch 23/30 150/150 [==============================] - 4s 25ms/step - loss: 0.1229 - accuracy: 0.9650 - precision_15: 0.9666 - val_loss: 0.1522 - val_accuracy: 0.9400 - val_precision_15: 0.9783 Epoch 24/30 150/150 [==============================] - 5s 33ms/step - loss: 0.1137 - accuracy: 0.9583 - precision_15: 0.9599 - val_loss: 0.0623 - val_accuracy: 0.9850 - val_precision_15: 0.9709 Epoch 25/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0627 - accuracy: 0.9800 - precision_15: 0.9832 - val_loss: 0.1041 - val_accuracy: 0.9650 - val_precision_15: 0.9346 Epoch 26/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0424 - accuracy: 0.9850 - precision_15: 0.9770 - val_loss: 0.1562 - val_accuracy: 0.9400 - val_precision_15: 0.9583 Epoch 27/30 150/150 [==============================] - 5s 33ms/step - loss: 0.0884 - accuracy: 0.9733 - precision_15: 0.9702 - val_loss: 0.0612 - val_accuracy: 0.9800 - val_precision_15: 0.9615 Epoch 28/30 150/150 [==============================] - 4s 26ms/step - loss: 0.0622 - accuracy: 0.9867 - precision_15: 0.9834 - val_loss: 0.0766 - val_accuracy: 0.9750 - val_precision_15: 0.9524 Epoch 29/30 150/150 [==============================] - 4s 25ms/step - loss: 0.0505 - accuracy: 0.9850 - precision_15: 0.9834 - val_loss: 0.0673 - val_accuracy: 0.9650 - val_precision_15: 0.9429 Epoch 30/30 150/150 [==============================] - 4s 26ms/step - loss: 0.1149 - accuracy: 0.9667 - precision_15: 0.9605 - val_loss: 0.1110 - val_accuracy: 0.9600 - val_precision_15: 0.9259
train_accuracy = history_combined_augmentation.history["accuracy"]
train_loss = history_combined_augmentation.history["loss"]
train_precision = history_combined_augmentation.history["precision_15"]
val_accuracy = history_combined_augmentation.history["val_accuracy"]
val_loss = history_combined_augmentation.history["val_loss"]
val_precision = history_combined_augmentation.history["val_precision_15"]
epochs = range(1, len(train_accuracy) + 1)
plt.plot(epochs, train_accuracy, "bo", label="Training accuracy")
plt.title("Training Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, train_loss, "bo", label="Training loss")
plt.title("Training Loss")
plt.legend()
plt.show()
plt.plot(epochs, train_precision, "bo", label="Training precision")
plt.title("Training Precision")
plt.legend()
plt.show()
plt.plot(epochs, val_accuracy, "bo", label="Validation accuracy")
plt.title("Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, val_loss, "bo", label="Validation loss")
plt.title("Validation Loss")
plt.legend()
plt.show()
plt.plot(epochs, val_precision, "bo", label="Validation precision")
plt.title("Validation Precision")
plt.legend()
plt.show()
# Let's loads the best-performing model and evaluate on the test data
model = keras.models.load_model("combined_augmentation_checkpoint_filepath")
model.evaluate(test_generator)
50/50 [==============================] - 1s 15ms/step - loss: 0.1426 - accuracy: 0.9600 - precision_15: 0.9259
[0.14260855317115784, 0.9599999785423279, 0.9259259104728699]
| Augmentation Type | Validation Accuracy | Test Accuracy |
|---|---|---|
| Rotation Augmentation (20 degrees) | 0.98 | 0.98 |
| Width Shift Augmentation (0.2) | 0.98 | 0.975 |
| Brightness Augmentation (0.5) | 0.965 | 0.955 |
| Horizontal Flip Augmentation | 0.96 | 0.965 |
| Combined Augmentation | 0.98 | 0.96 |